package net.rlair.sbdemo.aspect;

import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.After;
import org.aspectj.lang.annotation.AfterReturning;
import org.aspectj.lang.annotation.AfterThrowing;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;
import org.aspectj.lang.annotation.Pointcut;
import org.springframework.core.annotation.Order;
import org.springframework.stereotype.Component;

/**
 * aspect.
 */
@Component
@Aspect
@Order(2)
public class YuelulanAspect2 {

    @Pointcut("execution(* net.rlair.sbdemo.controller.UserController.list(..))")
    public void executeList() {

    }

    /**
     * 后置返回通知.
     * 这里需要注意的是:
     * 如果参数中的第一个参数为JoinPoint，则第二个参数为返回值的信息
     * 如果参数中的第一个参数不为JoinPoint，则第一个参数为returning中对应的参数
     * returning 限定了只有目标方法返回值与通知方法相应参数类型时才能执行后置返回通知，否则不执行，
     * 对于returning对应的通知方法参数为Object类型将匹配任何目标返回值
     *
     * @param joinPoint
     * @param result
     */
    @AfterReturning(value = "execution(* net.rlair.sbdemo.controller.UserController.list(..))", returning = "result")
    public void doAfterReturning(JoinPoint joinPoint, Object result) {
        System.out.println("后置返回值,目标方法返回值：" + result);
    }

    /**
     * 环绕通知.
     * 可以决定目标方法是否执行，什么时候执行，执行时是否需要替换方法参数，执行完毕是否需要替换返回值.
     * 环绕通知第一个参数必须是org.aspectj.lang.ProceedingJoinPoint类型
     */
    @Around("executeList()")
    public Object doAround(ProceedingJoinPoint proceedingJoinPoint) {
        System.out.println("环绕通知目标方法名：" + proceedingJoinPoint.getSignature().getName());
        try {
            // go on proceed
            Object obj = proceedingJoinPoint.proceed();//调用执行目标方法
            return obj;
        } catch (Throwable throwable) {
            throwable.printStackTrace();
        }
        return null;
    }

}